/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "dma.h"
#include "i2c.h"
#include "rtc.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "lcd.h"
#include "stdio.h"
#include "string.h" // ��� memset ����ͷ�ļ�
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
void LedScan(void);
void LedProcess(void);
void KeyScan(void);
void KeyProcess(void);
void Clock(void);
void DispScreen(void);
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
// ���尴������



// ����LED����

// ��˸��ض���
#define BLINK_INTERVAL 500  // ð����˸���(ms)
#define DIGIT_BLINK_INTERVAL 500 // ������˸���(ms)
#define ALARM_DURATION 5000 // ���㱨ʱ����ʱ��(ms)
#define LONG_PRESS_DURATION 2000 // ����ʱ��(ms)
#define DEBOUNCE_DELAY 50      // ���������ӳ�(ms)

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
extern RTC_HandleTypeDef hrtc;
RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;
char buf[30];
u8 RtcHour, RtcMinute, RtcSecond;       // RTCʱ��
u8 RtcYear, RtcMonth, RtcDay;           // RTC����
vu32 Time50msTick;                       // 50ms��ʱ��
vu32 Time1sTick;                         // 1s��ʱ��
RTC_TimeTypeDef sfm;
RTC_DateTypeDef nyrx;
u8 Trg, Cont, ReadData;
_Bool SCREEN = 0;           // ��ʾ��Ļ��־��0:��һ����1:�ڶ�����
_Bool ColonVisible = 1;     // ð����ʾ״̬
_Bool IsSettingTime = 0;    // ����ʱ��ģʽ��־
u8 SettingPos = 0;          // ����λ�ã�0:ʱ��1:�֣�2:�룩
_Bool IsAddMode = 1;        // �Ӽ�ģʽ��1:+��0:-��
u32 LastAdjustTime = 0;     // �ϴε���ʱ�䣨������
_Bool ValueChanged = 0;     // ��ֵ�ı��־
u32 LedFlashTime = 0;       // LED��˸ʱ��
_Bool LedFlashState = 0;    // LED��˸״̬
vu32 BlinkTime;          // ð����˸��ʱ��
vu32 DigitBlinkTime;     // ������˸��ʱ��
_Bool DigitVisible = 1;  // ������ʾ״̬��������˸��
_Bool IsAlarmActive = 0; // ���㱨ʱ״̬

// ����״̬�������ϲ������߼���
u32 KeyPressTime[4] = {0};  // ��¼����������ʱ��
_Bool KeyLongPressed[4] = {0}; // ������־

/* ����״̬���� */
typedef enum {
    KEY_STATE_RELEASED,  // �ͷ�״̬
    KEY_STATE_PRESSED,   // ����״̬
    KEY_STATE_LONG_PRESS // ����״̬
} KeyState;

/* ������Ϣ�ṹ�� */
typedef struct {
    GPIO_TypeDef* port;
    uint16_t pin;
    KeyState state;
    uint32_t pressTime;
    uint32_t lastDebounceTime;
    uint8_t debounceCount;
} KeyInfo;

/* ���尴������ */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
// �Զ��庯��������
void LedScan(void);
void LedProcess(void);
void KeyScan(void);
void KeyProcess(void);
void Clock(void);
void DispScreen(void);

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
u16 LedData=0xffff;
char buf [30];
u8 Hour=16, Minute=49, Second=30;
u8 Trg, Cont, ReadData;
vu32 TimelsTick;
vu32 Time50msTick;
vu32 Time500msTick;
_Bool FLASHFLAG ;
__IO uint32_t Time100msTick;
unsigned char LedState;
unsigned short LedVal[]={
0x7fff,0xbfff, 0xdfff,0xefff, 0xf7ff, 0xfbff, 0xfdff, 0xfeff,
0x7fff,0xbfff,0xdfff,0xefff,0xf7ff,0xfbff,0xfdff, 0xfeff,
0x7fff,0xbfff,0xdfff,0xefff,0xf7ff,0xfbff,0xfdff,0xfeff,
//从左到右3次
0xfeff,0xfdff,0xfbff,0xf7ff,0xefff,0xdfff,0xbfff,0x7fff,
0xfeff,0xfdff,0xfbff,0xf7ff,0xefff,0xdfff,0xbfff,0x7fff,
0xfeff, 0xfdff, 0xfbff, 0xf7ff, 0xefff,0xdfff,0xbfff,0x7fff,//从右到左3次
0x7eff,0xbdff,0xdbff,0xe7ff,
0x7eff,0xbdff,0xdbff,0xe7ff,
0x7eff,0xbdff,0xdbff,0xe7ff,
0xe7ff,0xdbff,0xbdff,0x7eff,
0xe7ff,0xdbff,0xbdff,0x7eff,
0xe7ff,0xdbff,0xbdff,0x7eff,
0x65ff,
0xaaff,0x55ff,0xaaff,0x55ff,0xaaff,
0x0fff,
0xf0ff,0x0fff,0xf0ff,0x0fff,0xf0ff,
0xffff
};
//从两边到中间亮
//从中间到两边亮
unsigned char LedCou;

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
  LCD_Init();

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	LCD_Clear(Black);
  LCD_SetBackColor(Black);
  LCD_SetTextColor(White);
//显示第1行“Digital clock”
  LCD_DisplayStringLine(Line2,(u8*)"   Digita1 Clock   ");
   sprintf(buf,"  %02u:%02u:%02u  ",Hour,Minute,Second);
  LCD_DisplayStringLine(Line4,(u8*)buf);
//启动定时
TimelsTick=uwTick;
Time50msTick=uwTick;
Time500msTick=uwTick;
Time100msTick=uwTick;
printf("Hello\r\n ");
 while (1)
{
  // 50ms��ʱ����
	LedProcess();
  if (uwTick - Time50msTick >= 50)
  {
    Time50msTick = uwTick;
    LedScan();
    KeyProcess();
    
    Clock();
   
    DispScreen();  // ��һ����ʾ��ǰʱ�䣨����ģʽ�»������ʾ����λ��
	}
  
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}


/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
	RCC_PeriphCLKInitTypeDef PeriphClkInit={0};

  /** Configure the main internal regulator output voltage
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV3;
  RCC_OscInitStruct.PLL.PLLN = 20;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
	
	PeriphClkInit.PeriphClockSelection=RCC_PERIPHCLK_USART1;
  PeriphClkInit.Usart1ClockSelection =RCC_USART1CLKSOURCE_PCLK2;
  if(HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit)!=HAL_OK)
	{
    Error_Handler();
   }
	}

/* USER CODE BEGIN 4 */
//LED灯扫描函数
void LedScan(void)
{
  GPIOC->ODR=LedData;
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
//LED灯数据处理函数
void LedProcess(void)
{
if(LedState==0)
{
   if(uwTick-Time100msTick>=100)
   {
    Time100msTick=uwTick;
    LedData =0x0100;
    if(++LedCou==50)
    {
     LedCou=0;
     LedState=1;
		}
	}
}
else if(LedState==1)
{
   if(uwTick-TimelsTick>=100)
   { 
     TimelsTick=uwTick;
     LedData = LedVal[LedCou];
     if(LedVal[++LedCou]==0xffff)LedCou=0;
    }
}
else {;}
}


void DispScreen(void)
//时钟数字的显示
{
	if(FLASHFLAG)
	{
		sprintf(buf,"  %02u:%02u:%02u  ",Hour,Minute,Second);
    LCD_DisplayStringLine(Line4,(u8*)buf);}
else
{
//将带变量的字符打印到buf数组
sprintf(buf,"  %02u %02u %02u  ",Hour,Minute,Second);
LCD_DisplayStringLine(Line4,(u8*)buf);
}
//设置闪烁标志
if(uwTick-Time500msTick>=500)
{
	 Time500msTick=uwTick;
   FLASHFLAG=!FLASHFLAG;
}
}
//键盘扫描函数
void KeyScan(void)
{
u8 State=0;
u8 BitState=0;
BitState=GPIOB->IDR;
State|=BitState&0x07;
BitState=GPIOA->IDR;
State|=(BitState&0x01)<<3;
ReadData=State^0x0f;
Trg=ReadData&(ReadData^Cont);
Cont=ReadData;
}

//键值处理函数
void KeyProcess(void)
{
KeyScan();
if(Trg==0x01)
//B1键按下
{
	printf("B1\r\n");
if(++Hour==24)
Hour=0;
}
else if(Trg==0x02)
//B2键按下
{
if(--Hour==0xff)
Hour=23;
printf("B2");
}


else if(Trg==0x04)
{
if(++Minute==60)
Minute=0;
}
else if(Trg==0x08) //B4键按下
{
if(--Minute==0xff)
	Minute=59;
}
else{;}
}

//时钟走时函数
void Clock (void)
{
//电子钟程序
if (uwTick-TimelsTick>=1000)
{
TimelsTick=uwTick;
if(++Second==60)
{
Second=0;
if(++Minute==60)
{
Minute=0;
if(++Hour==24)
Hour=0;
}
}
}
}

//printf函数重定向
int fputc(int ch,FILE *f)
{
	//串口发送函数
	HAL_UART_Transmit(&huart1,(u8*)&ch,1,50);
	return ch;
}


/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
